#include "mainwindow.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QWidget>
#include <QTimer>
#include <cmath>
#include <QKeyEvent>
#include <QLineEdit>
#include <QLabel>
#include <QDoubleValidator>
#include <QtMath>
#include <QCheckBox>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , sineSeries(new QLineSeries())
    , cosSeries(new QLineSeries())
    , currentX(0)
    , timer(new QTimer(this))
    , minYInput(new QLineEdit(this))
    , maxYInput(new QLineEdit(this))
    , sineCheckBox(new QCheckBox(this))
    , cosCheckBox(new QCheckBox(this))
{
    // Fullscreen mode
    showFullScreen();
    setWindowTitle("Sine and Cosine Plot (Corrected Labels)");
    setFocusPolicy(Qt::StrongFocus);

    // Control panel dimensions
    const int CONTROL_PANEL_WIDTH = 240;
    const int INNER_MARGIN = 20;
    const int CONTROL_WIDTH = CONTROL_PANEL_WIDTH - 2 * INNER_MARGIN;

    // Left control area
    QWidget *controlWidget = new QWidget(this);
    QVBoxLayout *controlLayout = new QVBoxLayout(controlWidget);
    controlLayout->setSpacing(15);
    controlLayout->setContentsMargins(INNER_MARGIN, INNER_MARGIN, INNER_MARGIN, INNER_MARGIN);
    controlWidget->setFixedWidth(CONTROL_PANEL_WIDTH);

    // Start Plot button
    QPushButton *startButton = new QPushButton("Start Plot", this);
    startButton->setMinimumHeight(40);
    startButton->setFixedWidth(CONTROL_WIDTH);
    controlLayout->addWidget(startButton);

    // Clear Chart button
    QPushButton *clearButton = new QPushButton("Clear Chart", this);
    clearButton->setMinimumHeight(40);
    clearButton->setFixedWidth(CONTROL_WIDTH);
    controlLayout->addWidget(clearButton);

    // Spacer
    controlLayout->addSpacing(10);

    // Sine checkbox
    QHBoxLayout *sineLayout = new QHBoxLayout();
    sineLayout->setSpacing(5);
    sineLayout->setContentsMargins(0, 0, 0, 0);
    QLabel *sineLabel = new QLabel("Show Sine Wave", this);
    sineLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    sineCheckBox->setChecked(true);
    int checkboxWidth = sineCheckBox->sizeHint().width();
    sineLabel->setFixedWidth(CONTROL_WIDTH - checkboxWidth - sineLayout->spacing());
    sineLayout->addWidget(sineLabel);
    sineLayout->addWidget(sineCheckBox);
    controlLayout->addLayout(sineLayout);

    // Cosine checkbox
    QHBoxLayout *cosLayout = new QHBoxLayout();
    cosLayout->setSpacing(5);
    cosLayout->setContentsMargins(0, 0, 0, 0);
    QLabel *cosLabel = new QLabel("Show Cosine Wave", this);
    cosLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    cosCheckBox->setChecked(true);
    cosLabel->setFixedWidth(sineLabel->width());
    cosLayout->addWidget(cosLabel);
    cosLayout->addWidget(cosCheckBox);
    controlLayout->addLayout(cosLayout);

    // Spacer
    controlLayout->addSpacing(10);

    // Y-axis scale label
    QLabel *yScaleLabel = new QLabel("Y-axis Scale:", this);
    yScaleLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    controlLayout->addWidget(yScaleLabel);

    // Minimum Y input
    QHBoxLayout *minYLayout = new QHBoxLayout();
    minYLayout->setSpacing(5);
    minYLayout->setContentsMargins(0, 0, 0, 0);
    QLabel *minYLabel = new QLabel("Min:", this);
    minYLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    minYLabel->setFixedWidth(40);
    minYInput->setFixedWidth(CONTROL_WIDTH - minYLabel->width() - minYLayout->spacing());
    minYInput->setValidator(new QDoubleValidator(-1000.0, 1000.0, 2, this));
    minYInput->setText("-1.0");
    minYLayout->addWidget(minYLabel);
    minYLayout->addWidget(minYInput);
    controlLayout->addLayout(minYLayout);

    // Maximum Y input
    QHBoxLayout *maxYLayout = new QHBoxLayout();
    maxYLayout->setSpacing(5);
    maxYLayout->setContentsMargins(0, 0, 0, 0);
    QLabel *maxYLabel = new QLabel("Max:", this);
    maxYLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    maxYLabel->setFixedWidth(minYLabel->width());
    maxYInput->setFixedWidth(minYInput->width());
    maxYInput->setValidator(new QDoubleValidator(-1000.0, 1000.0, 2, this));
    maxYInput->setText("1.0");
    maxYLayout->addWidget(maxYLabel);
    maxYLayout->addWidget(maxYInput);
    controlLayout->addLayout(maxYLayout);

    controlLayout->addStretch();

    // Main layout
    QWidget *centralWidget = new QWidget(this);
    QHBoxLayout *mainLayout = new QHBoxLayout(centralWidget);
    mainLayout->setContentsMargins(0, 0, 0, 0);
    mainLayout->addWidget(controlWidget);

    // Configure Sine Wave series (blue)
    sineSeries->setName("Sine Wave");
    QPen sinePen(Qt::blue, 2);
    sinePen.setCapStyle(Qt::RoundCap);
    sinePen.setJoinStyle(Qt::RoundJoin);
    sineSeries->setPen(sinePen);

    // Configure Cosine Wave series (red)
    cosSeries->setName("Cosine Wave");
    QPen cosPen(Qt::red, 2);
    cosPen.setCapStyle(Qt::RoundCap);
    cosPen.setJoinStyle(Qt::RoundJoin);
    cosSeries->setPen(cosPen);

    // Axes configuration - FIXED X-AXIS LABELING
    axisX = new QValueAxis();
    axisY = new QValueAxis();

    // X-axis with accurate π labeling
    const int PI_MULTIPLES = 10; // Show 0 to 10π
    axisX->setRange(0, PI_MULTIPLES * M_PI);
    axisX->setTickCount(PI_MULTIPLES + 1); // Ticks at 0, π, 2π, ..., 10π
    
    // Custom formatter to show exact π multiples
    axisX->setLabelFormat("%gπ");
    axisX->setTitleText("X Axis (radians)");

    // Initialize Y-axis
    updateYAxisScale();

    // Chart configuration
    chart = new QChart();
    chart->addSeries(sineSeries);
    chart->addSeries(cosSeries);
    chart->setAxisX(axisX, sineSeries);
    chart->setAxisX(axisX, cosSeries);
    chart->setAxisY(axisY, sineSeries);
    chart->setAxisY(axisY, cosSeries);
    chart->setTitle("Sine (0 at π, 2π...) & Cosine Waves (Press 'q' to quit)");
    chart->legend()->setVisible(true);
    chart->legend()->setAlignment(Qt::AlignBottom);

    // Chart background
    chart->setPlotAreaBackgroundBrush(QBrush(Qt::white));
    chart->setPlotAreaBackgroundVisible(true);

    // Chart view with anti-aliasing
    QChartView *chartView = new QChartView(chart);
    chartView->setRenderHint(QPainter::Antialiasing);
    chartView->setRenderHint(QPainter::TextAntialiasing);
    mainLayout->addWidget(chartView);

    setCentralWidget(centralWidget);

    // Timer for smooth plotting
    timer->setInterval(5);

    // Start button logic
    connect(startButton, &QPushButton::clicked, this, [=]() {
        updateYAxisScale();
        
        startButton->setEnabled(false);
        clearButton->setEnabled(false);
        minYInput->setEnabled(false);
        maxYInput->setEnabled(false);
        sineCheckBox->setEnabled(false);
        cosCheckBox->setEnabled(false);
        chart->setTitle("Plotting waves... (Sine = 0 at π, 2π...)");
        timer->start();
    });

    // Timer update logic - VERIFIED SINE BEHAVIOR
    connect(timer, &QTimer::timeout, this, [=]() {
        const double step = 0.01 * M_PI;
        double sineY = qSin(currentX);  // Mathematically correct: sin(π) = 0
        double cosY = qCos(currentX);   // cos(π) = -1
        
        // For verification, add reference points at π multiples
        if (qFuzzyCompare(currentX / M_PI, qRound(currentX / M_PI)) && 
            currentX > 0 && currentX <= 10 * M_PI) {
            // This will add small reference circles at π, 2π, etc.
            chart->addAnnotation(new QPointAnnotation(chart));
            chart->annotations().last()->setPoint(QPointF(currentX, 0));
            chart->annotations().last()->setVisible(true);
        }

        if (sineCheckBox->isChecked()) {
            sineSeries->append(currentX, sineY);
        }
        if (cosCheckBox->isChecked()) {
            cosSeries->append(currentX, cosY);
        }

        currentX += step;

        if (currentX > 10 * M_PI) {
            timer->stop();
            chart->setTitle("Sine (0 at π, 2π...) & Cosine Waves (Completed)");
            clearButton->setEnabled(true);
            minYInput->setEnabled(true);
            maxYInput->setEnabled(true);
            sineCheckBox->setEnabled(true);
            cosCheckBox->setEnabled(true);
        }
    });

    // Clear button logic
    connect(clearButton, &QPushButton::clicked, this, [=]() {
        timer->stop();
        sineSeries->clear();
        cosSeries->clear();
        // Remove all annotations
        foreach (QAbstractAnnotation *annotation, chart->annotations()) {
            chart->removeAnnotation(annotation);
            delete annotation;
        }
        currentX = 0;
        startButton->setEnabled(true);
        clearButton->setEnabled(false);
        minYInput->setEnabled(true);
        maxYInput->setEnabled(true);
        sineCheckBox->setEnabled(true);
        cosCheckBox->setEnabled(true);
        chart->setTitle("Sine (0 at π, 2π...) & Cosine Waves (Press 'q' to quit)");
    });

    // Checkbox toggled logic
    connect(sineCheckBox, &QCheckBox::toggled, this, [=](bool checked) {
        sineSeries->setVisible(checked);
    });

    connect(cosCheckBox, &QCheckBox::toggled, this, [=](bool checked) {
        cosSeries->setVisible(checked);
    });

    clearButton->setEnabled(false);
}

// Helper function to update Y-axis scale
void MainWindow::updateYAxisScale()
{
    double minY = minYInput->text().toDouble();
    double maxY = maxYInput->text().toDouble();
    
    if (minY >= maxY) {
        minY = -1.0;
        maxY = 1.0;
        minYInput->setText("-1.0");
        maxYInput->setText("1.0");
    }
    
    double range = maxY - minY;
    
    axisY->setRange(minY, maxY);
    axisY->setLabelFormat("%.1f");
    axisY->setTitleText("Y Axis (0.1 increments)");
    
    int majorIntervalCount = qCeil(range / 0.5);
    int minorTicksPerMajor = 4;
    
    axisY->setTickCount(majorIntervalCount + 1);
    axisY->setMinorTickCount(minorTicksPerMajor);
    
    axisY->setGridLineVisible(true);
    axisY->setGridLinePen(QPen(Qt::gray, 1));
    axisY->setMinorGridLineVisible(true);
    axisY->setMinorGridLinePen(QPen(Qt::lightGray, 1, Qt::DotLine));
}

// Handle 'q' key to quit
void MainWindow::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Q) {
        qApp->quit();
    } else {
        QMainWindow::keyPressEvent(event);
    }
}

MainWindow::~MainWindow()
{
    delete sineSeries;
    delete cosSeries;
    delete chart;
    delete axisX;
    delete axisY;
    delete sineCheckBox;
    delete cosCheckBox;
}
    